﻿using System;
using System.IO;
using System.Reflection;
using Microsoft.VisualBasic.ApplicationServices;
using MsSqlSpatial.Properties;
using MsSqlSpatial.Utility;
using YACLAP;

namespace MsSqlSpatial
{
    internal sealed class Program
    {
        private static void Main(string[] args)
        {
            DisplayProductInfo();

            using (var arg = new ArgParser(args, '-', '='))
            {
                if (String.Join("", args).Trim().Length == 0 || arg.Exists("help") || arg.Exists("h") || arg.Exists("?"))
                    DisplayHelp();
                else
                {
                    var sqlServerConnection = new ConnectionOptions();
                    var sqlServerOptions = new SqlServerOptions();

                    ExtractSqlServerArguments(arg, sqlServerConnection, sqlServerOptions);

                    if (arg.Exists("undeploy"))
                        Undeploy(sqlServerConnection);
                    else if (arg.Exists("deploy"))
                        Deploy(arg, sqlServerConnection);
                    else if (arg.Exists("import"))
                    {
                        bool appendRows = (0 ==
                                           string.Compare(arg.GetValueOrDefault("append_rows", "false"), "true", true));
                        switch (arg["import"].Value.ToLower())
                        {
                            case "shp":
                                ImportShapefile(arg, sqlServerConnection, sqlServerOptions, appendRows);
                                break;
                            case "pgsql":
                                ImportPostGis(arg, sqlServerConnection, sqlServerOptions, appendRows);
                                break;
                        }
                    }
                    else if (arg.Exists("export"))
                    {
                        //string export = arg["export"].Value.ToLower();
                        Console.WriteLine("Export not implemented yet");
                    }
                    else
                    {
                        Console.WriteLine("Unknown command. Please, read usage instructions below.");
                        Console.WriteLine();
                        DisplayHelp();
                    }
                }
#if DEBUG
                Console.WriteLine("Press any key to continue...");
                Console.ReadLine();
#endif
            }
        }

        private static void DisplayProductInfo()
        {
            var assemblyInfo = new AssemblyInfo(Assembly.GetExecutingAssembly());
            Console.WriteLine(string.Format(
                                  @"{0} (Build {1})
{2}
http://www.codeplex.com/MsSqlSpatial
",
                                  assemblyInfo.Title,
                                  assemblyInfo.Version,
                                  assemblyInfo.Copyright
                                  ));
        }

        private static void ExtractSqlServerArguments(ArgParser arg, ConnectionOptions sqlServerConnection,
                                                      SqlServerOptions sqlServerOptions)
        {
            string server = arg.GetValueOrDefault("server", Settings.Default.server);
            string db = arg.GetValueOrDefault("db", Settings.Default.db);
            string login = arg["login"].Value;
            string password = arg["password"].Value;
            string schema = arg.GetValueOrDefault("schema", Settings.Default.schema);
            string table = arg["table"].Value;
            string column = arg.GetValueOrDefault("column", Settings.Default.column);
            string sridArgument = arg.GetValueOrDefault("srid", Settings.Default.srid);
            string type = arg.GetValueOrDefault("type", Settings.Default.type);

            int srid = Convert.ToInt32(sridArgument);

            sqlServerConnection.Server = server;
            sqlServerConnection.Database = db;
            sqlServerConnection.Login = login;
            sqlServerConnection.Password = password;

            sqlServerOptions.Schema = schema;
            sqlServerOptions.Table = table;
            sqlServerOptions.Column = column;
            sqlServerOptions.SRID = srid;
            sqlServerOptions.Subtype = type;
        }

        private static void Undeploy(ConnectionOptions sqlServerConnection)
        {
            Console.WriteLine(string.Format("Undeploying from database '{0}' at {1}:",
                                            sqlServerConnection.Database,
                                            sqlServerConnection.Server));
            Console.WriteLine();
            Command.Undeploy(sqlServerConnection);
            Console.WriteLine();
            Console.WriteLine("MsSqlSpatial undeployed.");
        }

        private static void Deploy(ArgParser arg, ConnectionOptions sqlServerConnection)
        {
            string deployPermissionArgument =
                arg.GetValueOrDefault("deploy_permission", Settings.Default.deploy_permission).Trim().ToUpper();
            var deployPermission =
                (DeployPermission)
                Enum.Parse(typeof (DeployPermission), deployPermissionArgument.Replace("_", ""), true);
            Console.WriteLine(string.Format("Deploying to database '{0}' at {1}:",
                                            sqlServerConnection.Database,
                                            sqlServerConnection.Server));
            Console.WriteLine();
            Command.Deploy(sqlServerConnection, deployPermission);
            Console.WriteLine();
            Console.WriteLine("MsSqlSpatial deployed.");
        }

        private static void ImportShapefile(ArgParser arg, ConnectionOptions sqlServerConnection,
                                            SqlServerOptions sqlServerOptions, bool appendRows)
        {
            Console.WriteLine("Importing...");

            string filename = arg["shp_filename"].Value;
            TaskStats stats = Command.ImportShapefile(sqlServerConnection, sqlServerOptions, filename, appendRows);
            Console.WriteLine("{0} rows imported in {1} from shapefile '{2}'.",
                              stats.RowsProcessed,
                              StoredProcedures.FormatElapsedTime(stats.ElapsedTime),
                              Path.GetFileName(filename));
        }

        private static void ImportPostGis(ArgParser arg, ConnectionOptions sqlServerConnection,
                                          SqlServerOptions sqlServerOptions, bool appendRows)
        {
            Console.WriteLine("Importing...");

            string server = arg.GetValueOrDefault("pgsql_server", Settings.Default.pgsql_server);
            string db = arg.GetValueOrDefault("pgsql_db", Settings.Default.pgsql_db);
            string login = arg.GetValueOrDefault("pgsql_login", Settings.Default.pgsql_login);
            string password = arg["pgsql_password"].Value;

            string schema = arg.GetValueOrDefault("pgsql_schema", Settings.Default.pgsql_schema);
            string table = arg["pgsql_table"].Value;
            string geometryColumn = arg.GetValueOrDefault("pgsql_geom_column", Settings.Default.pgsql_geom_column);
            string identifierColumn = arg.GetValueOrDefault("pgsql_oid_column", Settings.Default.pgsql_oid_column);

            var postGisConnection = new ConnectionOptions
                                        {
                                            Server = server,
                                            Database = db,
                                            Login = login,
                                            Password = password
                                        };

            var postGisOptions = new PostGisOptions
                                     {
                                         Schema = schema,
                                         Table = table,
                                         GeometryColumn = geometryColumn,
                                         IdentifierColumn = identifierColumn
                                     };

            if (string.IsNullOrEmpty(sqlServerOptions.Table))
                sqlServerOptions.Table = postGisOptions.Table;

            TaskStats stats = Command.ImportPostGis(sqlServerConnection, postGisConnection, sqlServerOptions,
                                                    postGisOptions, appendRows);

            Console.WriteLine("{0} rows imported in {1} from PostGIS table '{2}'.", stats.RowsProcessed,
                              StoredProcedures.FormatElapsedTime(stats.ElapsedTime), postGisOptions.Table);
        }

        private static void DisplayHelp()
        {
            Stream resource = Assembly.GetExecutingAssembly().GetManifestResourceStream("MsSqlSpatial.README.txt");
            if (resource != null) Console.WriteLine(new StreamReader(resource).ReadToEnd());
        }
    }
}